import { HttpException, HttpStatus, Injectable, Logger } from "@nestjs/common";
import { CreateUserDto } from "./dto/create-user.dto";
import { UpdateUserDto } from "./dto/update-user.dto";
import { LoginUserDto } from "./dto/login-user.dto";
import { Repository } from "typeorm";
import { User } from "./entities/user.entity";
import { InjectRepository } from "@nestjs/typeorm";
import { plainToClass, plainToInstance } from "class-transformer";
import { UserAuthDto } from "./dto/login-user.vo";
import { AuthService } from "../../auth/auth.service";
import { wxLoginUserDto } from "./dto/wxLogin-user.dto";
import { HttpService } from "@nestjs/axios";
import { firstValueFrom } from "rxjs";
import { map } from "rxjs/operators";
import { serverConfig } from "../../common/config";
import { DateUtils } from "../../utils/date-utils";

@Injectable()
export class UserService {
  // 使用InjectRepository装饰器并引入Repository即可使用typeorm的操作
  constructor(
    private readonly httpService: HttpService,
    @InjectRepository(User) private readonly userRepository: Repository<User>,
    private authService: AuthService,
  ) {}

  // 微信授权登录
  async wxGenToken(wxLoginUserDto: wxLoginUserDto) {
    const { iv, encryptedData, code } = wxLoginUserDto;

    Logger.log(
      " wxGenToken 日志 ",
      JSON.stringify(wxLoginUserDto),
      " Service 1",
    );

    const params: any = {
      appid: serverConfig.WX_APPID,
      secret: serverConfig.WX_SECRET,
      grant_type: "authorization_code", // 写死
      js_code: code,
    };

    // 请求微信服务端接口 返回session_key和openid
    // const url = `https://api.weixin.qq.com/sns/jscode2session?grant_type=${this.grant_type}&appid=${this.appid}&secret=${this.secret}&js_code=${code}`
    const res = await firstValueFrom(
      this.httpService
        .get("https://api.weixin.qq.com/sns/jscode2session", { params })
        .pipe(map((response) => response.data)),
    );
    Logger.log(" 微信请求 日志 ", JSON.stringify(res), " Service ");
    const { openid, session_key, errcode, errmsg } = res;

    // 如果微信服务端抛出错误，则将错误直接返回给前端
    if (errcode) {
      // https://betheme.net/news/txtlist_i90049v.html?action=onClick
      throw new HttpException({ ...res }, HttpStatus.INTERNAL_SERVER_ERROR);
    }
    let user = null;
    user = await this.userRepository.findOne({
      where: { openid: openid },
    });
    if (!user) {
      // 注册微信新用户
      const userEntity = new User();
      userEntity.openid = openid;
      // https://developers.weixin.qq.com/community/develop/doc/00022c683e8a80b29bed2142b56c01
      userEntity.nickname = `京植能源用户${DateUtils.generateDateTimeWithRandom()}`;
      userEntity.avatar_url = null; //默认URL；
      userEntity.gender = 0;
      userEntity.status = 1;
      userEntity.is_admin = 0;
      user = await this.userRepository.save(userEntity);
    }
    const userVo = plainToClass(UserAuthDto, user);
    userVo.token = await this.authService.createToken({
      id: user.id,
      account: user.account,
      nickname: user.nickname,
      is_admin: user.is_admin,
      status: user.status,
      openid: user.openid,
    });
    return userVo;
  }

  // 帐号密码登陆 - 对接非微信业务
  async login(LoginUserDto: LoginUserDto) {
    const userLogin = plainToInstance(User, LoginUserDto);
    const user = await this.userRepository.findOne({
      where: { account: userLogin.account, pwd: userLogin.pwd },
    });
    if (!user) {
      throw new HttpException(
        {
          statusCode: HttpStatus.BAD_REQUEST,
          message: "账号或密码错误",
          error: "Invalid Credentials",
        },
        HttpStatus.BAD_REQUEST,
      );
    }
    const userVo = plainToClass(UserAuthDto, user);
    console.log(userVo, "userVo");
    userVo.token = await this.authService.createToken({
      id: user.id,
      account: user.account,
      nickname: user.nickname,
      is_admin: user.is_admin,
      status: user.status,
      openid: user.openid,
    });
    return userVo;
  }

  // 获取所有用户数据列表(productsRepository.query()方法属于typeoram)
  async getList(): Promise<User[]> {
    return await this.userRepository.query("select * from user");
  }

  async create(createUserDto: CreateUserDto) {
    const userEntity = plainToInstance(User, createUserDto);
    return await this.userRepository.save(userEntity);
  }

  findAll() {
    return `This action returns all user`;
  }

  findOne(id: number) {
    return `This action returns a #${id} user`;
  }

  update(id: number, updateUserDto: UpdateUserDto) {
    return `This action updates a #${id} ${JSON.stringify(updateUserDto)}`;
  }

  remove(id: number) {
    return `This action removes a #${id} user`;
  }
}
